package helper

import (
	"crypto/md5"
	"encoding/hex"
	"errors"
	"fmt"
	"math/rand"
	"net/url"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"time"

	"gitee.com/ander888/tools/zlog"
)

// 用于删除指定天数的指定目录下的日志文件
// logsDir：日志所在的目录  numDaysAgo：删除几天前的文件 hour minute：每天的几点几分执行
func DeleteOldLogFiles(logsDir string, numDaysAgo, hour, minute int) {
	// 获取当前时间
	now := time.Now()

	// 计算今天23:20的时间点
	nextRun := time.Date(now.Year(), now.Month(), now.Day(), hour, minute, 0, 0, now.Location())

	// 如果当前时间已经过了今天某时，则计算下一个的时间点
	if now.After(nextRun) {
		nextRun = nextRun.AddDate(0, 0, 1)
	}

	// 计算下次执行的等待时间
	waitDuration := nextRun.Sub(now)

	// 定时器，等待直到下一个执行时间点
	timer := time.NewTimer(waitDuration)
	<-timer.C

	// 执行删除操作
	err := filepath.Walk(logsDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		// 检查文件是否是普通文件且修改时间早于N天前
		if !info.IsDir() && info.ModTime().Before(now.AddDate(0, 0, -numDaysAgo)) {
			// 删除文件
			if err := os.Remove(path); err != nil {
				return err
			}
			zlog.Info("Deleted: " + path)
		}
		return nil
	})

	if err != nil {
		zlog.Err(err, "Delete failed")
	}

	// 递归调用，设置为每天执行
	DeleteOldLogFiles(logsDir, numDaysAgo, hour, minute)
}

func fileExists(filePath string) bool {
	// 使用 os.Stat 来获取文件信息
	_, err := os.Stat(filePath)
	if err != nil {
		return false
	}
	// 判断文件是否存在
	if os.IsNotExist(err) {
		return false
	}
	return true
}

// 获取指定目录下所有文件名，将文件后缀去掉
func GetDirAllFilesWithoutExt(dirPath string) (err error, fileNames []string) {
	err = filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return nil
		}
		if !info.IsDir() {
			fileName := filepath.Base(path)
			nameWithoutExt := strings.TrimSuffix(fileName, filepath.Ext(fileName))
			fileNames = append(fileNames, nameWithoutExt)
		}
		return nil
	})

	for _, name := range fileNames {
		if len(name) != 0 {
			fileNames = append(fileNames, name)
		}
	}
	return err, fileNames
}

// 获取指定目录下所有文件名,带后缀
func GetDirAllFiles(dirPath string) (err error, fileNames []string) {
	err = filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return errors.New("无法打开指定的目录: " + dirPath)
		}
		if !info.IsDir() {
			fileName := filepath.Base(path)
			nameWithoutExt := strings.TrimSuffix(fileName, filepath.Ext(fileName))
			fileNames = append(fileNames, nameWithoutExt)
		}
		return nil
	})

	for _, name := range fileNames {
		if len(name) != 0 {
			fileNames = append(fileNames, name)
		}
	}
	return err, fileNames
}

// 生成随机字符串函数
func GenerateRandomString(length int) string {
	const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	seededRand := rand.New(rand.NewSource(time.Now().UnixNano()))

	randomString := make([]byte, length)
	for i := range randomString {
		randomString[i] = charset[seededRand.Intn(len(charset))]
	}
	return string(randomString)
}

// 根据url获取protocol host：ip:port steamPath(已做唯一值处理格式为：ip+port/md5(url))
func GetUrlPrefix(rawURL string) (protocol, host, streamPath string) {
	parsedURL, err := url.Parse(rawURL)
	if err != nil {
		fmt.Println("Error parsing URL:", err)
		return
	}

	protocol = parsedURL.Scheme
	host = parsedURL.Host
	streamPath = filterSpecialChars(host) + "/" + generateUniqueValue(rawURL)
	return
}

// 按视频流全url生成唯一的流名称，目的是避免流名称冲突
func generateUniqueValue(input string) string {
	hasher := md5.New()
	hasher.Write([]byte(input))
	hash := hasher.Sum(nil)
	return hex.EncodeToString(hash)
}

// 过滤掉字符串中的特殊字符，只保留字符
func filterSpecialChars(input string) string {
	// 匹配非字母、数字、下划线的字符
	reg := regexp.MustCompile(`[^a-zA-Z0-9_]`)
	filtered := reg.ReplaceAllString(input, "")
	return filtered
}

// 检查视频流的url，将复杂的字符替换掉，此处以大华为案例
func FormatStreamUrl(streamUrl string) (newStreamUrl string) {
	protocol, _, _ := GetUrlPrefix(streamUrl)
	switch protocol {
	case "http":
		// 大华摄像头
		newStreamUrl1 := strings.Replace(streamUrl, "&subtype", "/subtype", 1)

		// 安讯士网络摄像机--单播&resolution=1280x720&fps=25
		newStreamUrl2 := strings.Replace(newStreamUrl1, "&resolution", "/resolution", 1)
		newStreamUrl3 := strings.Replace(newStreamUrl2, "&fps", "/fps", 1)
		// 安讯士网络摄像机--组播rtsp://root:123456@192.168.1.64/onvif-media/media.amp?profile=profile_1_h264&streamtype=multicast
		newStreamUrl = strings.Replace(newStreamUrl3, "&streamtype", "/streamtype", 1)
		return
	case "rtsp":
		newStreamUrl = strings.Replace(streamUrl, "&", "/", -1)
		return
	default:
		newStreamUrl = streamUrl
	}

	return
}

// 替换host为指定ip
func HostIpReplace(oldHost, sourceIp string) (newHost string) {
	index := strings.Index(oldHost, ":")
	if index == -1 {
		return sourceIp
	}

	// Replace characters before the symbol with the replacement character
	newHost = strings.Repeat(string(sourceIp), 1)
	newHost += oldHost[index:]

	return
}
